package cn.wolfcode.service.impl;

import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.common.web.Result;
import cn.wolfcode.domain.*;
import cn.wolfcode.feign.AlipayFeignApi;
import cn.wolfcode.feign.IntergralFeignApi;
import cn.wolfcode.mapper.OrderInfoMapper;
import cn.wolfcode.mapper.PayLogMapper;
import cn.wolfcode.mapper.RefundLogMapper;
import cn.wolfcode.mapper.SeckillProductMapper;
import cn.wolfcode.mq.MQConstant;
import cn.wolfcode.mq.OrderMQResult;
import cn.wolfcode.redis.SeckillRedisKey;
import cn.wolfcode.service.IOrderInfoService;
import cn.wolfcode.service.ISeckillProductService;
import cn.wolfcode.util.IdGenerateUtil;
import cn.wolfcode.web.msg.SeckillCodeMsg;
import com.alibaba.fastjson.JSON;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by wolfcode-lanxw
 */
@Slf4j
@Service
public class OrderInfoSeviceImpl implements IOrderInfoService {
    @Autowired
    private ISeckillProductService seckillProductService;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private PayLogMapper payLogMapper;
    @Autowired
    private RefundLogMapper refundLogMapper;

    @Autowired
    private SeckillProductMapper seckillProductMapper;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private AlipayFeignApi alipayFeignApi;


    @Autowired
    private IntergralFeignApi intergralFeignApi;

    @Value("${pay.returnUrl}")
    private String returnUrl;
    @Value("${pay.notifyUrl}")
    private String notifyUrl;



    @Override
    @Transactional()
    public String doSeckill(Long seckillId, int time,Long phone) {

        int i = seckillProductMapper.decrStock(seckillId);
        if(i==0){
            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
        }



        String orderno = this.creatOrder(seckillId,time,phone);
        redisTemplate.opsForSet().add(SeckillRedisKey.SECKILL_ORDER_SET.getRealKey(time + ""), phone + ":" + seckillId);
        return orderno;
    }

    public String creatOrder(Long seckillId, int time, Long phone) {
        Object vo = redisTemplate.opsForHash().get(SeckillRedisKey.SECKILL_PRODUCT_LIST.getRealKey(time+""), seckillId + "");
        SeckillProductVo seckillProductVo = JSON.parseObject(vo.toString(), SeckillProductVo.class);
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setProductCount(1);
        orderInfo.setProductId(seckillProductVo.getProductId());
        orderInfo.setSeckillId(seckillId);
        orderInfo.setSeckillPrice(seckillProductVo.getSeckillPrice());
        orderInfo.setCreateDate(new Date());
        orderInfo.setIntergral(seckillProductVo.getIntergral());
        orderInfo.setProductImg(seckillProductVo.getProductImg());
        orderInfo.setProductName(seckillProductVo.getProductName());
        orderInfo.setProductPrice(seckillProductVo.getProductPrice());
        orderInfo.setUserId(phone);
        orderInfo.setDeliveryAddrId(1l);
        orderInfo.setSeckillTime(time);
        orderInfo.setSeckillDate(new Date());
        orderInfo.setOrderNo(IdGenerateUtil.get().nextId()+"");
        int insert = orderInfoMapper.insert(orderInfo);
        return orderInfo.getOrderNo();
    }

    @Override
    @Transactional
    public void cancelTimeOrder(OrderMQResult orderMQResult) {

        log.info("进入了超时取消的流程");
        OrderInfo orderInfo = orderInfoMapper.find(orderMQResult.getOrderNo());
        if(orderInfo!=null){
            if (OrderInfo.STATUS_ARREARAGE.equals(orderInfo.getStatus())) {
                seckillProductMapper.incrStock(orderInfo.getProductId());
                seckillProductService.syncRedisStockCount(orderMQResult);
                rocketMQTemplate.sendOneWay(MQConstant.CANCEL_SECKILL_OVER_SIGE_TOPIC,orderMQResult.getSeckillId());
                orderInfoMapper.updateCancelStatus(orderInfo.getOrderNo(),OrderInfo.STATUS_TIMEOUT);
            }
        }
        //超时取消状态  库存和欲库存等的修改    恢复真实库存



    }

    @Override
    public OrderInfo find(String orderNo) {

        Object o = redisTemplate.opsForHash().get(SeckillRedisKey.SECKILL_ORDER_HASH.getRealKey(""), orderNo + "");
        if (o == null) {
            return null;
        }
        OrderInfo orderInfo = JSON.parseObject(o.toString(), OrderInfo.class);
        if(orderInfo==null){
            throw new BusinessException(SeckillCodeMsg.OPT_ERROR);
        }
        return orderInfo;
    }

    @Override
    public String payOnline(String orderNo) {
        System.out.println("同步调用的时间"+new Date());
        OrderInfo orderInfo = find(orderNo);
        PayVo payVo=new PayVo();
        payVo.setOutTradeNo(orderNo);
        payVo.setTotalAmount(orderInfo.getSeckillPrice()+"");
        payVo.setSubject(orderInfo.getProductName());
        payVo.setBody(orderInfo.getProductName());
        payVo.setReturnUrl(returnUrl);
        payVo.setNotifyUrl(notifyUrl);
        Result<String> result = alipayFeignApi.payOnline(payVo);
        if (result!=null&&!result.hasError()){
            System.out.println(result.getData());
            return result.getData();
        }
        return null;
    }

    @Override
    @Transactional
    public void paySuccess(String orderNo) {
        System.out.println("异步调用的时间"+new Date());
        OrderInfo orderInfo = find(orderNo);
        PayLog payLog = new PayLog();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        payLog.setNotifyTime(sdf.format(new Date()));
        //订单编号
        payLog.setTradeNo(orderNo);
        payLog.setPayType(OrderInfo.PAYTYPE_ONLINE);
        payLog.setTotalAmount(orderInfo.getSeckillPrice()+"");
        payLogMapper.insert(payLog);
        orderInfoMapper.changePayStatus(orderNo,OrderInfo.STATUS_ACCOUNT_PAID,OrderInfo.PAYTYPE_ONLINE);
    }

    @Override
    @Transactional
    public void refundOnline(String orderNo) {
        OrderInfo orderInfo = find(orderNo);
        RefundLog refundLog=new RefundLog();
        refundLog.setRefundTime(new Date());
        refundLog.setRefundAmount(orderInfo.getSeckillPrice()+"");
        refundLog.setRefundType(orderInfo.getPayType());
        refundLog.setOutTradeNo(orderNo);
        refundLog.setRefundReason("无");
        refundLogMapper.insert(refundLog);
        RefundVo refundVo=new RefundVo();
        refundVo.setRefundReason(refundLog.getRefundReason());
        refundVo.setRefundAmount(orderInfo.getSeckillPrice()+"");
        refundVo.setOutTradeNo(orderNo);
        Result<Boolean> booleanResult = alipayFeignApi.refundOnline(refundVo);

        if(booleanResult!=null&&!booleanResult.hasError()){
            if(!booleanResult.getData()){
                throw new BusinessException(SeckillCodeMsg.REFUND_ERROR);
            }
        }
        orderInfoMapper.changeRefundStatus(orderNo,OrderInfo.STATUS_REFUND);



        seckillProductMapper.incrStock(orderInfo.getProductId());


        OrderMQResult orderMQResult=new OrderMQResult();
        orderMQResult.setTime(orderInfo.getSeckillTime());
        orderMQResult.setSeckillId(orderInfo.getSeckillId());
        seckillProductService.syncRedisStockCount(orderMQResult);


        //最后修改本地标识
        rocketMQTemplate.sendOneWay(MQConstant.CANCEL_SECKILL_OVER_SIGE_TOPIC,orderInfo.getSeckillId());

    }

    @Override
    @Transactional
    public void payIntergral(String orderNo) {
        OrderInfo orderInfo = find(orderNo);
        PayLog payLog = new PayLog();
        payLog.setTradeNo(orderNo);
        payLog.setPayType(OrderInfo.PAYTYPE_INTERGRAL);
        payLog.setTotalAmount(orderInfo.getIntergral()+"");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        payLog.setNotifyTime(sdf.format(new Date()));
        int insert = payLogMapper.insert(payLog);

        //插入流水记录
        OperateIntergralVo operateIntergralVo=new OperateIntergralVo();
        operateIntergralVo.setPk(orderNo);
        operateIntergralVo.setValue(orderInfo.getIntergral());
        operateIntergralVo.setUserId(orderInfo.getUserId());
        operateIntergralVo.setInfo(orderInfo.getProductName());
        Result<String> stringResult = intergralFeignApi.decrIntergral(operateIntergralVo);
        if(stringResult==null||stringResult.hasError()){
            throw new BusinessException(SeckillCodeMsg.INTERGRAL_SERVER_ERROR);
        }

        //减少积分

        orderInfoMapper.changePayStatus(orderNo,OrderInfo.STATUS_ACCOUNT_PAID,OrderInfo.PAYTYPE_INTERGRAL);

        //修改订单状态
        //




    }

    @Override

    @GlobalTransactional
    public void refybdIntergral(String orderNo) {
        OrderInfo orderInfo = find(orderNo);
        RefundLog refundLog=new RefundLog();
        refundLog.setRefundTime(new Date());
        refundLog.setRefundAmount(orderInfo.getIntergral()+"");
        System.out.println(orderInfo.getPayType());
        refundLog.setRefundType(orderInfo.getPayType());
        refundLog.setOutTradeNo(orderNo);
        refundLog.setRefundReason("无");
        refundLogMapper.insert(refundLog);

        OperateIntergralVo operateIntergralVo=new OperateIntergralVo();
        operateIntergralVo.setPk(orderNo);
        operateIntergralVo.setValue(orderInfo.getIntergral());
        operateIntergralVo.setUserId(orderInfo.getUserId());
        operateIntergralVo.setInfo(orderInfo.getProductName());
        System.out.println(operateIntergralVo);
        Result<String> stringResult = intergralFeignApi.incrIntergral(operateIntergralVo);
        if (stringResult!=null&&!stringResult.hasError()){
            //修改订单状态
            orderInfoMapper.changeRefundStatus(orderNo,OrderInfo.STATUS_REFUND);
//            int i=1/0;

            seckillProductMapper.incrStock(orderInfo.getProductId());


            OrderMQResult orderMQResult=new OrderMQResult();
            orderMQResult.setTime(orderInfo.getSeckillTime());
            orderMQResult.setSeckillId(orderInfo.getSeckillId());
            seckillProductService.syncRedisStockCount(orderMQResult);


            //最后修改本地标识
            rocketMQTemplate.sendOneWay(MQConstant.CANCEL_SECKILL_OVER_SIGE_TOPIC,orderInfo.getSeckillId());



        }

    }


}
